﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PVFSLEAP
{


    /***************************************************************************************************
     * 1. 클래스: 이벤트 생성하는 클래스                                                           
     * 2. 설명: 허위공격을 발생하기 위한 클래스
     * 3. 입력 
     *     1) 
     * ************************************************************************************************/

    class C_EVNT
	{
		F_SETT	ST = new F_SETT(); // 인터페이스 객체 생성
		C_NODE	ND = new C_NODE(); // 노드객체 생성
		C_PVFS	PV = new C_PVFS(); // PVFS객체 생성
		C_COMM	CM = new C_COMM(); // 통신객체 생성

		Random C = new Random( ( int )DateTime.Now.Millisecond % 999 ); // 0~999까지 값
		Random K = new Random( ( int )DateTime.Now.Millisecond % 999 ); // 



        /***************************************************************************************************
         * 1. 함수: 공격할 CH 선택
         * 2. 설명: 허위 보고서나, 보트에 대한 이벤트 발생 할 CH 선택
         * 3. 입력 
         *     1) c: 랜덤 값의 다음에 있는 위치
         * ************************************************************************************************/
		public int chooseCH()
		{
			//System.Threading.Thread.Sleep( 1 );
			int c = C.Next( 1, 100 ); 
			return c;
		}

   /***************************************************************************************************
    * 1. 함수: 키 입력
    * 2. 설명: 센서필드에서의 클러스터헤드의 키
    * 3. 입력 
    *     1) k: 센서필드에서 키 할당
    * ************************************************************************************************/
		public int getKey()
		{
			System.Threading.Thread.Sleep( 1 );
			int k = K.Next( 0, ST.OCHLD - 1 );
			return k;
		}


   /***************************************************************************************************
    * 1. 함수: 공격 지역
    * 2. 설명: 센서필드에서의 클러스터헤드를 공격
    * 3. 입력 
    *     1) SN: 센서노드 갯수
    * ************************************************************************************************/
		public void attackFRIA( C_NODE[] SN )
		{
			int chnd = -1;
			int ndid = -1;
			int mvid = -1;
			int tvfv = 0;

			int vote = 0;

			chnd = chooseCH();
			//while ( true )
			//{
			//    chnd = chooseCH();
			//    if ( SN[chnd].CPNF == true )
			//        break;
			//}
			
			PV.generateReport( chnd, SN );// 공격할 노드 선택 후 보고서생성
			ndid = chnd;

			for ( int i=0; i < C_PVFS.vote.Count; i++ )
			{
				if ( C_PVFS.vote.GetByIndex(i).ToString() == "T" )  // vote 값이 맞으면 count 증가
					vote++;
			}


			if ( ( vote != 0 ) && ( vote < ST.OTVFV ) )
				SN[chnd].OFVI++;
			else if ( vote == ST.OTVFV )
				SN[chnd].OFRI++;

			//int numk = PV.generateKeys();
			//for ( int i = 0; i < numk; i++ )
			//{
			//SN[chnd].ENGY = CM.consumeTransmitting( SN[chnd].ENGY, 8 * numk );
			//SN[chnd].ENGY = CM.consumeReceiving( SN[chnd].ENGY, 8 * numk );			
			//}


    /***************************************************************************************************
    * 1. 내용: 드랍하는 부분
    * 2. 설명: 검증노드로 키 값 비교하여 드랍 
    * 3. 입력 
    *     1) k: 센서필드에서 키 할당
    * ************************************************************************************************/
			while ( true )
			{
				mvid = SN[ndid].PRID;
				SN[ndid].ENGY = CM.consumeReceiving( SN[ndid].ENGY, 24 );
				
				if ( ST.OPVFS == C_COMM.TRUE )
				{
					if ( PV.checkVerifiedNode( SN[mvid].HPCT, SN[chnd].HPCT ) == true )
					{
						int numk = PV.generateKeys();

						for ( int i = 0; i < SN[chnd].HPCT - SN[mvid].HPCT; i++ )
						{
							// Key Bytes
							SN[mvid].ENGY = CM.consumeTransmitting( SN[mvid].ENGY, numk * 4 );
							SN[mvid].ENGY = CM.consumeReceiving( SN[mvid].ENGY, numk * 4 );
						}

						for ( int i = 0; i < numk; i++ )
						{
							int keys = getKey();

							if ( C_PVFS.vote.Contains( keys ) == true )
							{
								if ( C_PVFS.vote[ keys ].ToString() == "T" )
								{
									if ( vote == 1 )
										SN[mvid].DFVI++;

									tvfv++;
									C_PVFS.vote[keys] = "F";
									break;
								}
							}
						}
					}
				}
				else if ( ST.OPPMT == C_COMM.TRUE ) // 같지 않으면 드랍하진 않고 레코드에 저장
				{
					if ( ndid == chnd )
					{
						for ( int i=0; i < C_PVFS.vote.Count; i++ )
						{
							if ( C_PVFS.vote.GetByIndex(i).ToString() == "T" )
							{
								if ( vote == 1 )
									SN[mvid].DFVI++;

								C_PVFS.vote[C_PVFS.vote.GetKey(i)] = "F";
								tvfv++;
							}
						}
					}
				}
				
				if ( tvfv >= ST.OTVFV )
				{
					SN[mvid].DFRI++;
					break;
				}

				if ( SN[mvid].NDID == 0 )
					break;

				SN[mvid].ENGY = CM.consumeTransmitting( SN[mvid].ENGY, 24 );
				ndid = mvid;
			}
		}

   /***************************************************************************************************
    * 1. 함수: 센서노드 웜홀 공격
    * 2. 설명: 특정센서에 웜홀 공격을 하여 에너지 소비
    * 3. 입력 
    *     1) SN: 센서노드
    * ************************************************************************************************/
		public void attackWormhole( C_NODE[] SN )
		{
			if ( ( ST.OLEAP == C_COMM.TRUE ) || ( ST.PPMT == C_COMM.TRUE ) )
			{
				for ( int i = 1; i < ST.OTTND; i++ )
				{
					if ( SN[i].WORM == true )
					{
						//for ( int c = 0; c < ST.OCHLD; c++ )
						//{
							double engy = CM.consumeReceiving( SN[i].ENGY, 1 );
							//SN[i].ENGY = engy * ST.OCHLD;
							SN[i].ENGY = engy*3;
							SN[i].OWRM++;
							SN[i].DWRM++;
							engy = CM.consumeTransmitting( SN[i].ENGY, 1 );
							//SN[i].ENGY = engy * ST.OCHLD;
							SN[i].ENGY = engy*3;
						//}
					}
				}
			}
		}
	}
}
